package com.g2room.search.life;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

import com.g2room.search.es.to.SearchResultPageTo;
public class Search {
	public static enum QueryType {
		/** OR查询，值为~ */
		OR("~"),
		/** 值为+ */
		AND("+"),
		/** 排除符号，值为- */
		EXCL("-");
		private String val;
		QueryType(String val) {this.val =val;}
		public String getVal(){return this.val;}
	}
	public Search(String index) {
		esClient = new EsClient(index);
	}
	private static EsClient esClient = null;
	static Connection conn = null;
	
	public static void main(String[] args) {
		String index = "life";
		
		Map<String, String> param = new HashMap<String, String>();
//		param.put("logo", "http://*");
//		param.put("code", "cthkj");
//		param.put("title", "肉干");
//		param.put("name", "版面编辑与校对");
//		param.put("name", "版面编辑与校对");
//		param.put("name", "版面编辑与校对");
//		param.put("name", "版面编辑与校对");
//		param.put("id", "1");
		Search search = new Search(index);
//		for(int i =0; i< 10; i++) {
		SearchResultPageTo srpt = search.searchAndPage(param, "lifeBeauty", 0, 10);
		for(Map<String, Object> map : srpt.getData()) {
			System.out.println(map.get("title").toString());// + "==" + map.get("univId").toString() +"="+ map.get("schoolName").toString());
//			updateImg(map.get("url").toString(), Integer.valueOf(map.get("schoolId").toString()));
		}
//			System.out.println(srpt.toString());
		
//		testAggregation();
	}
	
	public static void updateImg(String url, int id) {
		PreparedStatement grapPs = null;
		
		try {
			if(null == conn) conn = getMyuallConn();
			grapPs = conn.prepareStatement("update univ_info set images=? where id=?");
			grapPs.setString(1, url);
			grapPs.setInt(2, id);
			grapPs.execute();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(null != grapPs) {
				try {
					grapPs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public static Connection getMyuallConn() {
		Connection connection = null;
		try {
//				connection = new DbUtil().getConn("com.mysql.jdbc.Driver", 
//						"jdbc:mysql://203.171.236.56:3306/myuall?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&autoReconnectForPools=true", 
//						"root", "qwe!@#");
			
			connection = getConn("com.mysql.jdbc.Driver", 
					"jdbc:mysql://127.0.0.1:3306/myuall?useUnicode=true&characterEncoding=utf8&mysqlEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull", 
//					"op", "!wlms*yts_asw");
//				connection = new DbUtil().getConn("com.mysql.jdbc.Driver", 
//						"jdbc:mysql://127.0.0.1:3306/myuall?useUnicode=true&characterEncoding=utf8&mysqlEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull", 
						"root", "");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return connection;
	}

	/**
	 * 获取数据库连接对象，这里只获得，需要自己在使用后进行关闭。
	 *
	 * @return 数据库连接实例
	 * @throws ClassNotFoundException 
	 * @throws SQLException 
	 * @auther <a href="mailto:g2room@163.com">天涯</a>
	 * Jul 6, 2013 8:49:25 PM
	 */
	public static Connection getConn(String driverName, String url, String username, String pwd)
			throws ClassNotFoundException, SQLException {
		// 1.加载驱动
		Class.forName(driverName);
		// 2.得到连接
		return DriverManager.getConnection(url, username, pwd);
	}
	

	/**
	 * 搜索数据并分页显示
	 * @param param	key为字段名，value为查询值。说明：<br>
	 * 		and查询，则字段名前加+或不加任何修饰；默认就是必须包含；<br>
	 * 		or查询，则字段名前加~；<br>
	 * 		排除查询，则字段名前加-；<br>
	 */
	public SearchResultPageTo searchAndPage(Map<String, String> param, String type, int start, int size){
		SearchRequestBuilder searchRequestBuilder = esClient.getClient().prepareSearch(esClient.getIndex());
		searchRequestBuilder.setTypes(type);
		searchRequestBuilder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH);
//		PrefixQueryBuilder pqb = QueryBuilders.prefixQuery("banner", "http://");
//		bqb.queryName("banner");
		//设置查询关键字
		BoolQueryBuilder bqb = QueryBuilders.boolQuery();
		if(null != param && !param.isEmpty()) {
			for(String filed : param.keySet()) {
				// 获取第一个字符
				String firstChar = filed.substring(0, 1);
				if(firstChar.equals(QueryType.EXCL.getVal())) {
					bqb.mustNot(QueryBuilders.termQuery(filed.replace(QueryType.EXCL.getVal(), ""), param.get(filed)));
				} else if(firstChar.equals(QueryType.OR.getVal())) {
					bqb.should(QueryBuilders.termQuery(filed.replace(QueryType.OR.getVal(), ""), param.get(filed)));
				} else {
					bqb.must(QueryBuilders.termQuery(filed.replace(QueryType.AND.getVal(), ""), param.get(filed)));
				}
			}
		}
		searchRequestBuilder.setQuery(bqb).setFrom(start).setSize(size).setExplain(true);
//		searchRequestBuilder.addField("id").addField("code").addField("typeName");
		//.setSource("id").setSource("code")
		// 最后就是返回搜索响应信息
		SearchResponse response = searchRequestBuilder.execute().actionGet();
		SearchResultPageTo srpt = new  SearchResultPageTo();
		//获取搜索文档的结果
		SearchHits searchHits = response.getHits();
		srpt.setCount(searchHits.getTotalHits());
		SearchHit[] hits = searchHits.getHits();
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		for (int i = 0; i < hits.length; i++) {
			SearchHit hit = hits[i];
			resultList.add(hit.getSource());
		}
		srpt.setData(resultList);
		srpt.setSize(size);
		srpt.setStart(start);
		return srpt;
	}

	/**
	 * 根据ID查询对象信息
	 * @param id	对象ID
	 * @param type	索引TYPE
	 * @return	对象集合，key为属性，value为对于值
	 */
	public Map<String, Object> searchById(String id, String type){
		SearchRequestBuilder searchRequestBuilder = getSearchRequest(esClient.getIndex(), type);
		//设置查询关键字
		searchRequestBuilder.setQuery(QueryBuilders.termQuery(EsClient.FIELD_ID, id));
		// 最后就是返回搜索响应信息
		SearchResponse response = searchRequestBuilder.execute().actionGet();

		//获取搜索文档的结果
		SearchHits searchHits = response.getHits();
		SearchHit[] hits = searchHits.getHits();
		return null == hits || hits.length == 0 ? null :  hits[0].getSource();
	}

	/**
	 * 根据ID集合查询文档ID
	 * @param ids	业务ID集合
	 * @param type	索引类型
	 * @return
	 */
	public List<String> searchDocIdByIds(List<String> ids, String type){
		SearchRequestBuilder searchRequestBuilder = getSearchRequest(esClient.getIndex(), type);
		BoolQueryBuilder bqb = QueryBuilders.boolQuery();
		for(String id : ids) {
			bqb.should(QueryBuilders.termQuery(EsClient.FIELD_ID, id));
		}
		searchRequestBuilder.setQuery(bqb);
		SearchResponse response = searchRequestBuilder.execute().actionGet();
	    SearchHits hits = response.getHits();
	    List<String> result = new ArrayList<String>();
	    for (SearchHit hit : hits.getHits()) {
	    	result.add(hit.getId());
	    }
	    return result;
	}

	/**
	 * 根据id查询文档ID
	 * @param id	业务表id
	 * @param type	索引类型
	 * @return	索引文档ID
	 */
	public String searchDocIdById(String id, String type){
		SearchRequestBuilder searchRequestBuilder = getSearchRequest(esClient.getIndex(), type);
		BoolQueryBuilder bqb = QueryBuilders.boolQuery();
		bqb.should(QueryBuilders.termQuery(EsClient.FIELD_ID, id));
		searchRequestBuilder.setQuery(bqb);
		SearchResponse response = searchRequestBuilder.execute().actionGet();
	    SearchHits hits = response.getHits();
	    List<String> result = new ArrayList<String>();
	    for (SearchHit hit : hits.getHits()) {
	    	result.add(hit.getId());
	    }
	    return hits.getHits().length==0?"":hits.getHits()[0].getId();
	}

	public List<Map<String, Object>> searchByIds(List<Long> steamIds, String type){
		SearchRequestBuilder searchRequestBuilder = getSearchRequest(esClient.getIndex(), type);
		BoolQueryBuilder bqb = QueryBuilders.boolQuery();
		for(Long id : steamIds) {
			bqb.should(QueryBuilders.termQuery(EsClient.FIELD_ID, id));
		}
		searchRequestBuilder.setQuery(bqb);
		SearchResponse response = searchRequestBuilder.execute().actionGet();
	    SearchHits hits = response.getHits();
	    List<Map<String, Object>> result = new LinkedList<Map<String, Object>>();
	    for (SearchHit hit : hits.getHits()) {
	    	result.add(hit.getSource());
	    }
	    return result;
	}
	
	public SearchRequestBuilder getSearchRequest(String index, String type) {
		//创建查询索引
		SearchRequestBuilder searchRequestBuilder = esClient.getClient().prepareSearch(index);
		//设置查询索引类型
		searchRequestBuilder.setTypes(type);
		// 设置查询数据的位置,分页用
		searchRequestBuilder.setFrom(0);
		// 设置查询结果集的最大条数
		searchRequestBuilder.setSize(1060);
		// 设置查询结果集的最大条数
		searchRequestBuilder.setRouting(EsClient.getRouting(type));
		//设置查询类型
		//1.SearchType.DFS_QUERY_THEN_FETCH = 精确查询
		// 2.SearchType.SCAN = 扫描查询,无序
		// 3.SearchType.COUNT = 不设置的话,这个为默认值,还有的自己去试试吧
		searchRequestBuilder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH);
		return searchRequestBuilder;
	}
	

	/**
	 * 搜索数据并分页显示
	 * @param param	key为字段名，value为查询值。说明：<br>
	 * 		and查询，则字段名前加+或不加任何修饰；默认就是必须包含；<br>
	 * 		or查询，则字段名前加~；<br>
	 * 		排除查询，则字段名前加-；<br>
	 */
	public SearchResultPageTo searchGroup(Map<String, String> param, String type, int start, int size){
		SearchRequestBuilder searchRequestBuilder = esClient.getClient().prepareSearch(esClient.getIndex());
		searchRequestBuilder.setTypes(type);
		searchRequestBuilder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH);
		//设置查询关键字
		BoolQueryBuilder bqb = QueryBuilders.boolQuery();
		if(null != param && !param.isEmpty()) {
			for(String filed : param.keySet()) {
				// 获取第一个字符
				String firstChar = filed.substring(0, 1);
				if(firstChar.equals(QueryType.EXCL.getVal())) {
					bqb.mustNot(QueryBuilders.termQuery(filed.replace(QueryType.EXCL.getVal(), ""), param.get(filed)));
				} else if(firstChar.equals(QueryType.OR.getVal())) {
					bqb.should(QueryBuilders.termQuery(filed.replace(QueryType.OR.getVal(), ""), param.get(filed)));
				} else {
					bqb.must(QueryBuilders.termQuery(filed.replace(QueryType.AND.getVal(), ""), param.get(filed)));
				}
			}
		}
		searchRequestBuilder.setQuery(bqb).setFrom(start).setSize(size).setExplain(true);
		// 最后就是返回搜索响应信息
		SearchResponse response = searchRequestBuilder.execute().actionGet();
		SearchResultPageTo srpt = new  SearchResultPageTo();
		//获取搜索文档的结果
		SearchHits searchHits = response.getHits();
		srpt.setCount(searchHits.getTotalHits());
		SearchHit[] hits = searchHits.getHits();
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		for (int i = 0; i < hits.length; i++) {
			SearchHit hit = hits[i];
			resultList.add(hit.getSource());
		}
		srpt.setData(resultList);
		srpt.setSize(size);
		srpt.setStart(start);
		return srpt;
	}
	
//	public static void testAggregation() {
//		SearchRequestBuilder srb = esClient.getClient().prepareSearch(esClient.getIndex());
//        srb.setTypes("univImage");
//        srb.setSearchType(SearchType.QUERY_AND_FETCH);
//
//        TermsBuilder gradeTermsBuilder = AggregationBuilders.terms("schoolAgg").field("schoolId");
////        TermsBuilder classTermsBuilder = AggregationBuilders.terms("classAgg").field("class");
////        gradeTermsBuilder.subAggregation(classTermsBuilder);
//
//        srb.addAggregation(gradeTermsBuilder);
//
//        SearchResponse sr = srb.execute().actionGet();
//
//        Map<String, Aggregation> aggMap = sr.getAggregations().asMap();
//
//        StringTerms schoolTerms = (StringTerms) aggMap.get("schoolAgg");
//
//        Iterator<Bucket> schoolBucketIt = schoolTerms.getBuckets().iterator();
//
//        while(schoolBucketIt.hasNext()) {
//            Bucket schoolBucket = schoolBucketIt.next();
//            System.out.println(schoolBucket.getKey() + "年级有" + schoolBucket.getDocCount() +"个学生。");
////
////            StringTerms classTerms = (StringTerms) gradeBucket.getAggregations().asMap().get("classAgg");
////            Iterator<Bucket> classBucketIt = classTerms.getBuckets().iterator();
////
////            while(classBucketIt.hasNext())
////            {
////                Bucket classBucket = classBucketIt.next();
////                System.out.println(gradeBucket.getKey() + "年级" +classBucket.getKey() + "班有" + classBucket.getDocCount() +"个学生。");
////            }
//            System.out.println();
//        }
//
//    }
}
